package com.llap.exp190929.controller;

import com.llap.exp190929.dto.PaginatedDto;
import com.llap.exp190929.entity.User;
import com.llap.exp190929.error.ForbiddenException;
import com.llap.exp190929.error.RestException;
import com.llap.exp190929.error.UnauthorizedException;
import com.llap.exp190929.security.JwtUser;
import com.llap.exp190929.service.UserService;
import com.llap.exp190929.util.Util;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("users")
@AllArgsConstructor
@CrossOrigin
@Slf4j
public class UsersController {
    private UserService userService;

    @GetMapping("")
    @PreAuthorize("hasAuthority('admin')")
    public PaginatedDto<User> findUsers(
            @RequestParam(required = false, defaultValue = "1") Integer page,
            @RequestParam(required = false, defaultValue = "20") Integer pageSize,
            @RequestParam(required = false, defaultValue = "") String keyword) {
        PaginatedDto<User> ret = PaginatedDto.from(userService.findUsers(page, pageSize, keyword));
        ret.getData().forEach(e -> e.setPassword(null));
        return ret;
    }

    @GetMapping("{id}")
    public User getUser(@PathVariable Integer id) {
        return userService.findUser(id).eraseCredential();
    }

    @PostMapping("")
    @PreAuthorize("hasAuthority('admin')")
    public User insertUser(@RequestBody User user) {
        if (user.getPassword() == null || user.getPassword().isEmpty()) {
            user.setPassword("123456");
        }
        return userService.addUser(user);
    }

    @PatchMapping("")
    public User updateUser(@RequestBody User user) throws RestException {
        JwtUser loggedUser = Util.getLoginUser();
        if (loggedUser != null) {
            if (loggedUser.getAuthorities().contains(new SimpleGrantedAuthority("admin")) ||
                    loggedUser.getId().equals(user.getId())) {
                User ret = userService.updateUser(user);
                return ret == null ? null : ret.eraseCredential();
            }
            else {
                throw new UnauthorizedException("Not authorized");
            }
        }
        else {
            throw new UnauthorizedException("");
        }
    }

    @DeleteMapping("")
    @PreAuthorize("hasAuthority('admin')")
    public void deleteUser(@RequestParam Integer id) throws RestException {
        JwtUser jwtUser = Util.getLoginUser();
        if (jwtUser != null && id.equals(jwtUser.getId())) {
            throw new ForbiddenException("You cannot delete your own account");
        }
        userService.deleteUser(id);
    }
}
